﻿using System;
using System.Linq;
using FarmerJoe.ClassSettings;
using FarmerJoe.Helpers;
using FarmerJoe.Helpers.Units;
using FarmerJoe.Settings;
using Levelbot.Actions.Death;
using Styx;
using Styx.CommonBot;
using Styx.TreeSharp;
using Action = Styx.TreeSharp.Action;
using FarmerJoe.Helpers.Logging;

namespace FarmerJoe.Classes
{
    public static partial class Druid
    {
        public static Composite CombatBehavior_Feral
        {
            get
            {
                return new PrioritySelector(
                    
                    Spells.WaitForCast(),
                    Misc.EnsureTarget(),

                    

                    // Bear Form if we need to
                    new Decorator(ret => CLC.ResultOK(FpswareSettings.Instance.Druid.FeralBearForm), CombatBehavior_Guardian),

                    //new Common.NeedToUseLifeSpirit(new Common.UseLifeSpirit()),
                    Common.UseHealthManaRegenAgent(ClassParser.HealthPotion, ClassParser.ManaPotion),

                    AllFormsHeal(),
                    AllFormsNaturesVigil(),

                    // If we're back here and we're still in Bear Form then lets try to use one last ability
                    Spells.Cast("Maul", ret => Me.Shapeshift == ShapeshiftForm.Bear && Me.CurrentRage > 30),

                    Inventory.UseTrinket1(),
                    Inventory.UseTrinket2(),
                    
                    Spells.Cast("Cat Form", ret => Me.Shapeshift != ShapeshiftForm.Cat),
                    Movement.MoveToLOS(),
                    Movement.FaceTarget(),

                    Spells.Cast("Incarnation", ret => CLC.ResultOK(FpswareSettings.Instance.Druid.FeralBerserk)),

                    // Silence!
                    new Decorator(ret=> CT.IsCasting && Timers.SpellOkToCast("Silence Bitch",1500) && CT.CastingSpell.CastTime >= 1,
                        new PrioritySelector(
                            
                            new Sequence(
                                Spells.Cast("Skull Bash", ret => CLC.ResultOK(FpswareSettings.Instance.Druid.FeralSkullBash) && CT.Distance < 13),
                                new Action(ret => Log.Write(Colours.InformativeColour, string.Format("Target is casting {0}, silencing with Skull Bash", CT.CastingSpell.Name)))
                                ),
                                
                            new Sequence(
                                Spells.Cast("Mighty Bash", ret => CLC.ResultOK(FpswareSettings.Instance.Druid.FeralMightyBash)),
                                new Action(ret => Log.Write(Colours.InformativeColour, string.Format("Target is casting {0}, silencing with Mighty Bash", CT.CastingSpell.Name)))
                                )
                            )),
                    
                    Spells.CastOnGround("Force of Nature",ret=> CT.Location, ret => CLC.ResultOK(FpswareSettings.Instance.Druid.FeralTrents)),
                    
                    Spells.BuffSelf("Savage Roar", ret => !Me.HasAura("Savage Roar") && TalentsAndGlyphs.HasGlyph("Savagery")  && CLC.ResultOK(FpswareSettings.Instance.Druid.SavageRoar)),
                    Spells.Cast("Rip", ret => !FpswareSettings.Instance.Druid.Rip.Contains("never") && Me.ComboPoints >= Convert.ToInt32(FpswareSettings.Instance.Druid.RipMinComboPoints) && CT.HealthPercent > FpswareSettings.Instance.Druid.RipMinTargetHealth && CT.AuraTimeLeft("Rip", true).TotalSeconds <= 3),
                    Spells.Cast(FpswareSettings.Instance.Druid.Finisher, ret => (Me.ComboPoints >= 5 && Me.CurrentEnergy > 30) || (Me.ComboPoints >= Convert.ToInt32(FpswareSettings.Instance.Druid.FinisherComboPoints) && CT.HealthPercent <= FpswareSettings.Instance.Druid.FinisherTargetHealth)),
                    Spells.Cast("Survival Instincts", ret =>  Me.HealthPercent < FpswareSettings.Instance.Druid.FeralSurvivalInstincts),

                    // Tiger's Fury or Berserk. You can only have one
                    new Decorator(ret=> !Me.HasAura("Tiger's Fury") && !Me.HasAura("Berserk"),
                        new PrioritySelector(
                            Spells.Cast("Berserk", ret => CLC.ResultOK(FpswareSettings.Instance.Druid.FeralBerserk)),
                            Spells.Cast("Tiger's Fury", ret => Me.EnergyPercent < FpswareSettings.Instance.Druid.TigersFuryMinEnergy && CLC.ResultOK(FpswareSettings.Instance.Druid.TigersFury))
                            )),

                    // Incarnation, do some additional stuff
                    new Decorator(ret => Me.HasAura("Incarnation: King of the Jungle"),
                        new PrioritySelector(
                            Spells.Cast("Pounce", ret => !CT.HasDebuff("Pounce Bleed") && CT.HealthPercent > 50 && CLC.ResultOK(FpswareSettings.Instance.Druid.IncarnationPounce) && Timers.SpellOkToCast("Incarnation Pounce", 3000)),
                            Spells.Cast("Ravage", ret => CLC.ResultOK(FpswareSettings.Instance.Druid.IncarnationRavage) && Timers.SpellOkToCast("Incarnation Ravage", 3000))
                            )
                        
                        ),
                    
                    Spells.Cast("Wild Charge", ret => CT.Distance > 5 && CT.Distance < 25 && CLC.ResultOK(FpswareSettings.Instance.Druid.FeralWildCharge)),
                    Spells.Cast("Faerie Fire", ret => (CT.AuraTimeLeft("Faerie Fire") < 3 && CT.AuraTimeLeft("Faerie Swarm") < 3) && CLC.ResultOK(FpswareSettings.Instance.Druid.FeralFaerieFire)),
                    
                    Spells.Cast("Savage Roar", ret => !Me.HasAura("Savage Roar") && Me.ComboPoints >= 1 && Me.ComboPoints <= Convert.ToInt32(FpswareSettings.Instance.Druid.SavageRoarMaxCP) && CLC.ResultOK(FpswareSettings.Instance.Druid.SavageRoar)),

                    Spells.Cast("Disorienting Roar", ret => !FpswareSettings.Instance.Druid.FeralDisorientingRoar.Contains("never") && AddsAndOthers.HasAdds &&
                        ((FpswareSettings.Instance.Druid.FeralDisorientingRoar.Contains("only on adds") && CT.HostileUnitsNearTarget(10f).Count() >= 2) ||
                        (FpswareSettings.Instance.Druid.FeralDisorientingRoar.Contains("3+") && CT.HostileUnitsNearTarget(10f).Count() >= 3) ||
                        (FpswareSettings.Instance.Druid.FeralDisorientingRoar.Contains("4+") && CT.HostileUnitsNearTarget(10f).Count() >= 4) ||
                        (FpswareSettings.Instance.Druid.FeralDisorientingRoar.Contains("5+") && CT.HostileUnitsNearTarget(10f).Count() >= 5)
                        )),


                        // Moved further up the tree to now be above the finisher
                    //Spells.Cast("Rip", ret => !FpswareSettings.Instance.Druid.Rip.Contains("never") && Me.ComboPoints >= Convert.ToInt32(FpswareSettings.Instance.Druid.RipMinComboPoints) && CT.HealthPercent > FpswareSettings.Instance.Druid.RipMinTargetHealth && CT.AuraTimeLeft("Rip", true).TotalSeconds <= 3),
                        
                    // Finisher spell
                    new Decorator(ret => (FpswareSettings.Instance.Druid.FeralThrash.Contains("always") || (FpswareSettings.Instance.Druid.FeralThrash.Contains("adds") && CT.HostileUnitsNearTarget(8f).Count() >= 2)),
                        new Decorator(ret => !CT.IsCrowdControlledUnitNearTarget(8f),
                            new PrioritySelector(
                                Spells.Cast("Thrash", ret => !CT.HasMyAura("Thrash"))
                                ))),

                    Spells.Cast("Rake", ret => CT.AuraTimeLeft("Rake",true).TotalSeconds < 3 && CLC.ResultOK(FpswareSettings.Instance.Druid.Rake) && Timers.SpellOkToCast("Rake",2000)),
                    Spells.Cast("Shred", ret => CT.MeIsSafelyBehind && CLC.ResultOK(FpswareSettings.Instance.Druid.Shred)),
                    Spells.Cast("Mangle",ret=> (Me.EnergyPercent > FpswareSettings.Instance.Druid.FeralMangleEnergy || Me.HasAura("Clearcasting"))),

                    // Bit of a fall through just to get the job done. 
                    Spells.Cast("Mangle", ret => (Me.EnergyPercent >= Spells.PowerCost("Mangle")) && !AddsAndOthers.HasAdds && CT.HealthPercent < 30),

                    Movement.MoveToMelee(true)
                    );
            }
        }

        public static Composite PullBehavior_Feral
        {
            get
            {
                return new PrioritySelector(

                    Spells.WaitForCast(),
                    Misc.EnsureTarget(),
                    new Sequence(ret => Me.Mounted, new Action(ret => Spells.Dismount("Pulling")), new Action(ctx => RunStatus.Failure)),
                    Movement.MoveToLOS(),
                    Movement.FaceTarget(),



                    Spells.BuffSelf("Cat Form", ret => Me.Shapeshift != ShapeshiftForm.Cat),

                    // User defined pull options
                    new Decorator(ret=> FpswareSettings.Instance.Druid.FeralPull.Contains("user defined"),
                        new PrioritySelector(
                            Spells.BuffSelf("Prowl", ret => FpswareSettings.Instance.Druid.FeralPullProwl.Contains("always") && !Me.HasAura("Prowl")),
                            Spells.Cast("Faerie Fire", ret => !Me.HasAura("Prowl") && FpswareSettings.Instance.Druid.FeralPullFaerieFire.Contains("always")),
                            Spells.Cast("Mangle", ret => FpswareSettings.Instance.Druid.FeralPullProwl.Contains("never") && FpswareSettings.Instance.Druid.FeralPullFaerieFire.Contains("never"))
                            )),

                    // If you're prowling use these spells...
                    Spells.Cast("Ravage", ret => Me.HasAura("Prowl") && CT.MeIsSafelyBehind && CT.IsWithinMeleeRange && CLC.ResultOK(FpswareSettings.Instance.Druid.FeralPullRavage)),
                    Spells.Cast("Pounce", ret => Me.HasAura("Prowl") && CT.IsWithinMeleeRange && CLC.ResultOK(FpswareSettings.Instance.Druid.FeralPullPounce)),

                    // Standard stuff to get us closer
                    Spells.Cast("Wild Charge", ret => CT.Distance > 5 && CT.Distance < 25 && CLC.ResultOK(FpswareSettings.Instance.Druid.FeralWildCharge)),
                    Spells.Cast("Dash", ret => Me.HasAura("Prowl") && CT.Distance2DSqr > 25*25),
                    Spells.Cast("Stampeding Roar", ret => CT.Distance2D > 35 * 35 && SpellManager.HasSpell("Dash") && SpellManager.Spells["Dash"].Cooldown),
                    
                    // Flying targets are ALWAYS pulled with Faerie Fire
                    Spells.Cast("Faerie Fire", ret => !CT.HasMyAura("Faerie Fire") && CT.IsFlying),

                    // Fall through for unexpected pulls if you don't have given spells
                    Spells.Cast("Mangle", ret => ((Me.HasAura("Prowl") && !SpellManager.HasSpell("Pounce") && !SpellManager.HasSpell("Ravage")) || 
                        (FpswareSettings.Instance.Druid.FeralPullFaerieFire.Contains("always") && !SpellManager.HasSpell("Faerie Fire"))
                        
                        )),

                    // Automatic fall through stuff
                    new Decorator(ret => FpswareSettings.Instance.Druid.FeralPull.Contains("automatic"),
                        new PrioritySelector(
                            Spells.Cast("Pounce", ret => Me.HasAura("Prowl")),
                            Spells.Cast("Mangle", ret => true),
                            Spells.Cast("Faerie Fire", ret => true)
                            )),

                    Movement.MoveToMelee(true)
                    );
            }
        }
    }
}
